
package convertTestsToJUnit;


import java.util.Arrays;
import java.util.List;
import java.util.LinkedList;
import java.util.Set;
import java.util.HashSet;
import model.Filter;
import model.MethodDeclared;
import model.TestClusterBuilder;
import util.GAConfig;
import operations.AssignConstant;
import operations.CreateArray;
import operations.CreateObject;
import operations.InvokeMethod;
import operations.Operation;
import ga.GAInfo;
import ga.Individual;

public class RemoveUselessInitialCons implements TestTransformation {

	public static final RemoveUselessInitialCons singleton = new RemoveUselessInitialCons();

	@Override
	public Individual perform(Individual test,GAInfo gaInfo) {		
		Operation[] ops = new Operation[test.getStatements().size()];
		test.getStatements().toArray(ops);
		Set<String> referenceExisted=new HashSet<String>();
		for (Operation op : ops) {
			if(op instanceof CreateObject) {
				String ref= ((CreateObject)op).getRef();
				referenceExisted.add(ref);
				 List<Class<?>> inputClasses =((CreateObject)op).getConstructor().getInputTypes();
				  List<Object> values = ((CreateObject)op).getValues();
				     for(int j=0;j<values.size();j++){
				    	 Class<?> paramTpe = inputClasses.get(j);
				    	 if(Filter.isPrimitiveOrStringType(paramTpe)||paramTpe==null ||values.get(j)==null)continue;
						 referenceExisted.add(values.get(j).toString());
				     }
			} else if(op instanceof InvokeMethod) {
//				 System.out.println(op);
				String ref= ((InvokeMethod)op).getReturn();
					referenceExisted.add(ref);
				ref= ((InvokeMethod)op).getThis();
				referenceExisted.add(ref);
				 List<Class<?>> inputClasses =((InvokeMethod)op).getMethod().getInputTypes();
				  List<Object> values = ((InvokeMethod)op).getValues();
				     for(int j=0;j<values.size();j++){
				    	 Class<?> paramTpe = inputClasses.get(j);
//				    	 System.out.println(paramTpe.getName());
				    	 if(Filter.isPrimitiveOrStringType(paramTpe)||paramTpe==null ||values.get(j)==null)continue;
						 referenceExisted.add(values.get(j).toString());
				     }
				     
				 
			}else if(op instanceof AssignConstant) {
				String ref= ((AssignConstant)op).getRefrence();
				if(referenceExisted.contains(ref)) continue;
				referenceExisted.add(ref);
			}else if(op instanceof CreateArray) {
				String ref= ((CreateArray)op).getReference();
				if(referenceExisted.contains(ref)) continue;
				referenceExisted.add(ref);
			}
		}
		Operation[] initialConst = new Operation[test.getInitialConstructors().size()];
		test.getInitialConstructors().toArray(initialConst);
		List<Operation> reducedInitialConst=new LinkedList<Operation>();

		for (Operation op : initialConst) {
			if(op instanceof CreateObject) {
				String ref= ((CreateObject)op).getRef();
				if(!referenceExisted.contains(ref))continue;
				reducedInitialConst.add(op);
			}else if(op instanceof AssignConstant) {
				String ref= ((AssignConstant)op).getRefrence();
				if(!referenceExisted.contains(ref)) continue;
				reducedInitialConst.add(op);
			}else if(op instanceof CreateArray) {
				String ref= ((CreateArray)op).getReference();
				if(!referenceExisted.contains(ref)) continue;
				reducedInitialConst.add(op);
			}
			
		}	
	     return new Individual(reducedInitialConst,Arrays.asList(ops));

	}
	

}